from datetime import datetime, timezone
from typing import Optional

from sqlmodel import SQLModel, Field, Relationship


class Permission(SQLModel, table=True):
    """权限表"""
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(unique=True, index=True, max_length=100)
    code: str = Field(unique=True, index=True, max_length=100)  # 权限代码，用于前端控制用
    description: str |  None = Field(default=None, max_length=200)
    resource_type: str = Field(max_length=50)       # 资源类型：menu,button,api
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())
    updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())

    # 定义关系
    # RolePermission模型中有一个名为permission的字段，它与当前Permission模型中的role_permissions字段相互关联
    role_permissions: list["RolePermission"] = Relationship(back_populates="permission")

class Menu(SQLModel, table=True):
    """菜单表"""
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(max_length=50)
    path: str = Field(max_length=200)
    component: str | None = Field(default=None,max_length=200)
    icon: str | None = Field(default=None,max_length=50)
    parent_id: int | None = Field(default=None, foreign_key="menu.id")
    order: int = Field(default=0)
    is_active: bool = Field(default=True)
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())

    # 定义关系
    menu_permissions: list["MenuPermission"] = Relationship(back_populates="menu")
    children: list["Menu"] = Relationship(back_populates="parent")
    parent: Optional["Menu"] = Relationship(
        # 指定父级菜单,自关联关系
        sa_relationship_kwargs={"remote_side": "Menu.id"},
        # 指定反向关系字段名为children
        back_populates="children"
    )

class Role(SQLModel, table=True):
    """角色表"""
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True, unique=True, max_length=50)
    code: str = Field(index=True, unique=True, max_length=50)   # 角色代码
    description: str | None = Field(default=None, max_length=200)
    is_active: bool = Field(default=True)
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())
    updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())

    # 关系
    user_roles: list["UserRole"] = Relationship(back_populates="role")
    role_permissions: list["RolePermission"] = Relationship(back_populates="role")

class User(SQLModel, table=True):
    """用户表"""
    id: int | None = Field(default=None, primary_key=True)
    username: str = Field(index=True, unique=True, max_length=50)
    email: str = Field(index=True, unique=True, max_length=100)
    full_name: str | None = Field(default=None,max_length=100)
    hashed_password: str = Field(max_length=255)
    is_active: bool = Field(default=True)
    is_superuser: bool = Field(default=False)
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())
    updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).astimezone())

    # 关系
    user_roles: list["UserRole"] = Relationship(back_populates="user")

    def set_password(self, password: str):
        """设默密码"""
        import bcrypt
        self.hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")

    def check_password(self, password: str):
        """验证密码"""
        import bcrypt
        return bcrypt.checkpw(password.encode("utf-8"), self.hashed_password.encode("utf-8"))

class UserRole(SQLModel, table=True):
    """用户角色关联表"""
    id: int | None = Field(default=None, primary_key=True)
    user_id: int = Field(default=None, foreign_key="user.id")
    role_id: int = Field(default=None, foreign_key="role.id")

    # 关系
    user: User = Relationship(back_populates="user_roles")
    role: Role = Relationship(back_populates="user_roles")

class RolePermission(SQLModel, table=True):
    """角色权限关联表"""
    id: int | None = Field(default=None, primary_key=True)
    role_id: int = Field(default=None, foreign_key="role.id")
    permission_id: int = Field(default=None, foreign_key="permission.id")

    # 关系
    role: Role = Relationship(back_populates="role_permissions")
    permission: Permission = Relationship(back_populates="role_permissions")

class MenuPermission(SQLModel, table=True):
    """菜单权限关联表"""
    id : int | None = Field(default=None, primary_key=True)
    menu_id: int = Field(default=None, foreign_key="menu.id")
    permission_id: int = Field(default=None, foreign_key="permission.id")

    # 关系
    menu: Menu = Relationship(back_populates="menu_permissions")
    permission: Permission = Relationship()



